package tum0r.json;

/**
 * 工程: XJSON<br>
 * 包: tum0r.utils<br>
 * 创建者: tum0r<br>
 * 创建时间: 2020/10/31 11:11<br>
 * <br>
 */
public class AVL {
    public JSONNode rootNode;

    public AVL(JSONNode rootNode) {
        this.rootNode = rootNode;
    }

    private boolean check(JSONNode node) {
        boolean result = false;
        if (node != null && Math.abs(node.leftHeight - node.rightHeight) > 1) {
            result = true;
        }
        return result;
    }

    /**
     * 四种失衡情况<br>
     * 左左    1001<br>
     * 左右    1002<br>
     * 右左    2001<br>
     * 右右    2002<br>
     *
     * @param node 失衡节点
     * @return 失衡情况
     */
    public int checkType(JSONNode node) {
        int result = -1;
        if (node != null) {
            if (node.leftHeight > node.rightHeight) {
                result = 1000;
                node = node.leftNode;
            } else if (node.leftHeight < node.rightHeight) {
                result = 2000;
                node = node.rightNode;
            }

            if (node.leftHeight > node.rightHeight) {
                result += 1;
            } else if (node.leftHeight < node.rightHeight) {
                result += 2;
            }
        }
        return result;
    }

    public JSONNode check() {
        if (check(this.rootNode)) {
            JSONNode tempNode = this.rootNode;
            while (check(tempNode)) {
                if (tempNode.leftHeight > tempNode.rightHeight) {
                    tempNode = tempNode.leftNode;
                } else {
                    tempNode = tempNode.rightNode;
                }
            }
            tempNode = tempNode.rootNode;
            int type = checkType(tempNode);
            switch (type) {
                case 1002:
                    tempNode.leftNode = tempNode.leftNode.rightNode;
                    tempNode.leftNode.rootNode.rightNode = tempNode.leftNode.leftNode;
                    tempNode.leftNode.leftNode = tempNode.leftNode.rootNode;
                    tempNode.leftNode.rootNode = tempNode;
                    tempNode.leftNode.leftNode.rootNode =  tempNode.leftNode;

                    tempNode.leftNode.leftNode.rightHeight = Math.max(tempNode.leftNode.leftNode.rightNode.leftHeight, tempNode.leftNode.leftNode.rightNode.rightHeight) + 1;
                    tempNode.leftNode.leftHeight = Math.max(tempNode.leftNode.leftNode.leftHeight, tempNode.leftNode.leftNode.rightHeight) + 1;
                    tempNode.leftHeight = Math.max(tempNode.leftNode.leftHeight, tempNode.leftNode.rightHeight) + 1;
                case 1001:
                    tempNode = tempNode.leftNode;
                    tempNode.rootNode.leftNode = tempNode.rightNode;
                    tempNode.rightNode = tempNode.rootNode;
                    tempNode.rootNode = tempNode.rightNode.rootNode;
                    tempNode.rightNode.rootNode = tempNode;
                    tempNode.rightNode.leftNode.rootNode = tempNode.rightNode;

                    tempNode.rightNode.leftHeight = Math.max(tempNode.rightNode.leftNode.leftHeight, tempNode.rightNode.leftNode.rightHeight) + 1;
                    tempNode.rightHeight = Math.max(tempNode.rightNode.leftHeight, tempNode.rightNode.rightHeight) + 1;
                    break;
                case 2002:
                case 2001:
                    break;
            }
            while (tempNode.rootNode != null) {
                tempNode = tempNode.rootNode;
            }
            this.rootNode = tempNode;
        }
        return this.rootNode;
    }
}
